package com.bjsdzk.collector.rpc;

import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSONArray;
import com.bjsdzk.backend.rpc.serial.SerialPortService;
import com.bjsdzk.collector.constant.Constant;
import com.bjsdzk.collector.entity.agreement.SendCmd;
import com.bjsdzk.collector.entity.model.Command;
import com.bjsdzk.collector.mapper.CommandMapper;
import com.bjsdzk.collector.one2one.BasetVerticle;
import com.bjsdzk.collector.one2one.OnlyServer;
import com.bjsdzk.collector.one2one.StartModServer;
import com.bjsdzk.collector.utils.CRC16;
import com.bjsdzk.collector.utils.StrUtils;
import com.bjsdzk.collector.utils.Utils;
import com.google.common.base.Joiner;
import io.vertx.core.Vertx;
import io.vertx.core.eventbus.EventBus;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.redis.RedisClient;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service(
        version = "1.0.0",
        interfaceClass = SerialPortService.class
)
@Component
public class SerialPortServiceImp implements SerialPortService {

    private static Logger logger = LoggerFactory.getLogger(SerialPortServiceImp.class);

    @Autowired
    private Vertx vertx;
    @Autowired
    private RedisClient redis;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Autowired
    private StartModServer startModServer;
    @Autowired
    private CommandMapper commandMapper;
    @Autowired
    private ConfigurableApplicationContext context;

    @Override
    public void deviceAdd(String json) {
        logger.info("receive deviceAdd msg: " + json);
        JsonObject config = new JsonObject(json);
        String port = config.getString("port");
        int p = Integer.parseInt(port);
        if (p < 1 || p > 65535) {
            logger.error("port:{} add check no pass");
            return;
        }
        String dtuType = config.getString("dtuType");
        getTypeRedis(config, dtuType);
        String key = "mod_" + port;
        String key_deviceList = "deviceList";
        redis.exists(key, (h) -> {
            if (h.result() > 0) {
                if (StringUtils.equals(dtuType, Constant.DTUTYPE_13)) {
//                     redis.hget(key, key_deviceList, res -> {
//                         JsonArray array = new JsonArray(res.result());
//                         vertx.eventBus().send(Constant.MOD_SEND_SET_MODEL + port,config);
//                         array.addAll(new JsonArray(config.getString(key_deviceList)));
//                         HashSet<String> hashSet = new HashSet(array.getList());
//                         redis.hset(key, key_deviceList, new JsonArray(new ArrayList<>(hashSet)).toString(), setRes -> {
//                         });
//                     });

                    new JsonArray(config.getString(key_deviceList)).forEach((device) -> {
                        redis.hmset(BasetVerticle.getRedisKeyByDeviceId(device.toString()), new JsonObject().put("companyId", config.getString("companyId")).put("deviceId", device).put("lineStatus", false).put("lastDataTime", 0).put("hardwareType", config.getString("hardwareType")).put("currentRatio",1).put("source", config.getString("source")!=null?config.getString("source"):"platform"), setRedisResult -> {

                        });
                    });
                }
            } else {
                redis.hmset("mod_" + port, config, h1 -> {

                });
                startModServer.startModServer(config);
            }
        });
    }

    @Override
    public void deviceDelete(String json) {
        logger.info("receive deviceDelete msg: " + json);
        JsonObject config = new JsonObject(json);
        String port = config.getString("port");
        String key = "mod_" + port;
        if (StringUtils.equals("62001", port)) {
            return;
        }
        String key_deviceList = "deviceList";
        redis.hgetall(key, res -> {
            JsonObject result = res.result();
            if (StringUtils.equals(result.getString("dtuType"), Constant.DTUTYPE_13)) {
                JsonArray objects = new JsonArray(config.getString(key_deviceList));
                objects.forEach(device -> {
                    redis.del(BasetVerticle.getRedisKeyByDeviceId(device.toString()), rlt -> {
                        if (rlt.succeeded()) {
                            logger.debug("del port success==>" + key);
                            vertx.eventBus().send(Constant.MOD_SEND_SET_MODEL + port,config);
                        } else {
                            logger.debug("del port fail==>" + key);

                        }
                    });
                });
            } else {
                if (res.result() != null) {
                    String deploymentID = result.getString("deploymentID");
                    vertx.undeploy(deploymentID);
                }

                redis.del(key, rlt -> {
                    if (rlt.failed()) {
                        logger.debug("del port fail==>" + key);
                    } else {
                        logger.debug("del port success==>" + key);
                    }
                });
            }


        });
    }

    @Override
    public void setModel( String s) {
        logger.info("receive setModel msg: " + s);
        JsonObject config = new JsonObject(s);
        String port = config.getString("port");
        String dtuType = config.getString("dtuType");
        getTypeRedis(config,dtuType);
        this.redis.hmset("mod_" + port, config, res -> {
            if(res.succeeded()){
                vertx.eventBus().send(Constant.MOD_SEND_SET_MODEL + port,config);
            }else {
                logger.error(Utils.addStr("port:",port,"==> set model fail"));
            }
        });
    }

    @Override
    public void cmd( String s) {
        JsonObject cmdConfig = new JsonObject(s);
        logger.info("send cmd interface:"+cmdConfig.toString());
        Integer port = cmdConfig.getInteger("port");
        String dtuType = cmdConfig.getString("dtuType");
        String deviceType = cmdConfig.getString("deviceType");
        if (StringUtils.equals(dtuType, Constant.DTUTYPE_6)) {

            Integer deviceNum = cmdConfig.getInteger("deviceNum");
            String sendId = cmdConfig.getString("sendId");
            String value = cmdConfig.getString("value");
            String flag = cmdConfig.getString("flag");
            String source = cmdConfig.getString("source");
            String messageId = cmdConfig.getString("messageId");

            String sendCmd = "";
            String devicestr = "";


            if (StringUtils.equals(sendId, "signal")) {
                sendCmd = "at-usr.cnAT+CSQ\r";
            } else {

                devicestr = String.format("%02x", deviceNum).toUpperCase();
                String[] splitAddress = sendId.split("~");
                String startAddress = splitAddress[0].substring(0, 4);
                String endAddress = splitAddress[splitAddress.length - 1].substring(0, 4);
                List<Command> comm = new ArrayList<>();
                if (StringUtils.equals(Constant.DEVICETYPE_116, deviceType) || StringUtils.equals(Constant.DEVICETYPE_106, deviceType)) {
                    deviceType = Constant.DEVICETYPE_106;
                    comm = commandMapper.findAllByAddressAll(startAddress, endAddress, deviceType);
                } else if (StringUtils.equals(Constant.DEVICETYPE_117, deviceType)) {
                    comm = commandMapper.findAllBySendIdAll(splitAddress[0], splitAddress[splitAddress.length - 1],
                            deviceType);
                }
                if (!comm.isEmpty()) {
                    startAddress = comm.get(0).getAddress();
                } else {
                    logger.info("无此命令");
                    return;
                }
                int b = 0;
                String hexValue = "";
                if (StringUtils.equals(flag, "write")) {
                    String[] splitValue = value.split("~");
                    for (int i = 0; i < comm.size(); i++) {
                        if (sendId.length() > 4) {
                            b = b + 1;
                            int binaryValue = 0;
                            String binaryType = "";
                            if (StringUtils.equals(splitAddress[i].substring(4), "0")) {
                                binaryType = Integer.toBinaryString(0);
                                binaryValue = Integer.parseInt(splitValue[i]);
                            } else if (StringUtils.equals(splitAddress[i].substring(4), "1")) {
                                binaryType = Integer.toBinaryString(1);
                                binaryValue = Integer.parseInt(splitValue[i]);
                            } else if (StringUtils.equals(splitAddress[i].substring(4), "2")) {
                                binaryType = Integer.toBinaryString(2);
                                binaryValue = Integer.parseInt(splitValue[i]) + 3000;
                            } else if (StringUtils.equals(splitAddress[i].substring(4), "3")) {
                                binaryType = Integer.toBinaryString(3);
                                binaryValue = Integer.parseInt(splitValue[i]) * 10;
                            } else if (StringUtils.equals(splitAddress[i].substring(4), "4")) {
                                binaryType = Integer.toBinaryString(4);
                                binaryValue = Integer.parseInt(splitValue[i]) * 10;
                            }

                            String v = Utils.addStr(String.format("%03d", Long.parseLong(binaryType)),
                                    String.format("%013d", Long.parseLong(Long.toBinaryString(binaryValue))));
                            hexValue = hexValue + String.format("%04x", Integer.valueOf(v, 2));
                        } else {
                            b = b + comm.get(i).getByteNum();
                            String type = comm.get(i).getType();
                            if (StringUtils.equals(type, "5")) {
                                String v = String.format("%02x",
                                        Integer.parseInt(splitValue[i]));
                                hexValue = hexValue + v + v;
                            }
                            if (StringUtils.equals(type, "6")) {
                                hexValue = hexValue + String.format("%04x", Integer.parseInt(splitValue[i]));
                            } else if (StringUtils.equals(type, "10")) {
                                hexValue = hexValue + String.format("%04x", Integer.parseInt(splitValue[i]) * 10);
                            } else if (StringUtils.equals(type, "11")) {
                                hexValue = hexValue + splitValue[i];
                            } else if (StringUtils.equals(type, "12")) {
                                for (String st : splitValue[i].split("-")) {
                                    hexValue = hexValue + String.format("%04x", Integer.parseInt(st));
                                }
                            } else if (StringUtils.equals(type, "13")) {
                                Integer len = comm.get(i).getByteNum() * 4;
                                hexValue = hexValue + String.format("%0" + len + "x", Integer.parseInt(splitValue[i]));
                            } else if (StringUtils.equals(type, "15")) {
                                Integer len = comm.get(i).getByteNum() * 4;
                                hexValue = hexValue + String.format("%0" + len + "x", Long.parseLong(splitValue[i]) * 10000);
                            } else if (StringUtils.equals(type, "17")) {
                                Integer len = comm.get(i).getByteNum() * 4;
                                hexValue = hexValue + String.format("%0" + len + "x", Long.parseLong(splitValue[i]) * 100);
                            }
                        }
                    }
                }
                String byteLength = String.format("%02x", b * 2);
                String byteNum = String.format("%04x", b);

                if (StringUtils.equals(Constant.DEVICETYPE_116, deviceType) || StringUtils.equals(Constant.DEVICETYPE_106, deviceType)) {
                    if (StringUtils.equals(flag, "write")) {
                        sendCmd = Utils.checkNumSecondAll(
                                Utils.addStr(devicestr + "10", startAddress, byteNum, byteLength, hexValue));
                    } else {
                        sendCmd = Utils.checkNumSecondAll(
                                Utils.addStr(devicestr + "03", startAddress, String.format("%04x", comm.stream().mapToInt(Command::getByteNum).sum())));
                    }

                } else if (StringUtils.equals(Constant.DEVICETYPE_117, deviceType)) {
                    if (StringUtils.equals(flag, "write")) {
                        sendCmd = "68" + Utils.checkNumFisrtAll(
                                Utils.addStr("F0", devicestr + "10", startAddress, byteNum, byteLength, hexValue));
                    } else {
                        sendCmd = "68" + Utils.checkNumFisrtAll(Utils.addStr("F0", devicestr + "03", startAddress,
                                String.format("%04x", comm.stream().mapToInt(Command::getByteNum).sum()) + ""));
                    }

                }
            }
            logger.info("port:" + port + "-->send cmd:" + sendCmd);
            vertx.eventBus().send("mod.connector.cmd." + port, new JsonObject().put("port", port).put("cmd", sendCmd).put("source", source).put("messageId", messageId));
        } else if (StringUtils.equals(dtuType, Constant.DTUTYPE_7)) {
            String deviceCode = cmdConfig.getString("deviceCode");
            String oper = cmdConfig.getString("oper");
            String source = cmdConfig.getString("source");
            String messageId = cmdConfig.getString("messageId");
            String l = String.format("%02x", deviceCode.length() / 2);
            String cmd=null;
            if (StringUtils.equals("B0", oper)){
                String data = cmdConfig.getString("data");
                String dataHex = String.format("%02x", Integer.parseInt(data));
                cmd = OnlyServer.splicCmd("8881B0030A" + "0000000000000000", l+deviceCode + dataHex);
            }else if(StringUtils.equals("A0", oper)){
                cmd= OnlyServer.splicCmd("8881", "A0", "030A" + "0000000000000000", l+deviceCode + "00");
            }else if(StringUtils.equals("A1", oper)){
                JsonArray data = cmdConfig.getJsonArray("data");
                String dataHex = String.format("%02x", data.size());
               String content =data.stream().map(str ->{
                    JsonObject json = new JsonObject(str.toString());
                    String params=json.getString("params");
                    int value= json.getInteger("value");
                    return params+"02"+String.format("%04x", value);
                }).reduce(dataHex,(a, b) -> a + b) ;
                cmd= OnlyServer.splicCmd("8881", oper, "030A" + "0000000000000000", l+deviceCode + content);
//                cmd= OnlyServer.splicCmd("8881", oper, "030A" + "0000000000000000", l+deviceCode + "01"+"2102"+"02"+"0032");
            }
            EventBus eventBus = vertx.eventBus();
            logger.info("port:" + port + " deviceCode："+deviceCode+"-->send cmd:" + cmd);
            eventBus.publish(Constant.ONLY_CMD  + port+"_"+deviceCode, new JsonObject().put("cmd", cmd).put("messageId", messageId).put("source", source));
        }else if (StringUtils.equals(dtuType, Constant.DTUTYPE_12)) {

            String source = cmdConfig.getString("source");

            String operation = cmdConfig.getString("operation");
            Integer function = cmdConfig.getInteger("function");
            String messageId = cmdConfig.getString("messageId");
            List<String> deviceList = cmdConfig.getJsonArray("deviceList").getList();
            Boolean isSave = cmdConfig.getBoolean("isSave");
            int cmdIdLn = (int)(Math.random()*100+200);


            SendCmd sendCmd = lnSendCmd(port, source, cmdIdLn, operation, function, deviceList, messageId, isSave);
            sendCmd.setCallback(true);
            vertx.eventBus().publish(Constant.ONLY_CMD + port, JsonObject.mapFrom(sendCmd));

            SendCmd getsendCmd = lnSendCmd(port, source, 125, Constant.LNCMDTYPE_CONTRL, 5, deviceList, messageId, isSave);
            vertx.eventBus().publish(Constant.ONLY_CMD + port, JsonObject.mapFrom(getsendCmd));
        }else if (StringUtils.equals(dtuType, Constant.DTUTYPE_11)) {
            String source = cmdConfig.getString("source");
            String messageId = cmdConfig.getString("messageId");
            String operation = cmdConfig.getString("operation");
            List<String> deviceList = cmdConfig.getJsonArray("deviceList").getList();
            Boolean isSave = cmdConfig.getBoolean("isSave");
            Integer startAddress = cmdConfig.getInteger("startAddress");

            deviceList.forEach((l) -> {
                String deviceHex = String.format("%04x", Integer.parseInt(l));
                String content;
                if (StringUtils.equals("02", operation)){
                    List<Integer> values = cmdConfig.getJsonArray("values").getList();
                    String value = values.stream().map((v) ->
                            String.format("%04x", v)
                    ).reduce("", (a, b) ->
                            StringUtils.join(a, b));
                    content = StringUtils.join(deviceHex, operation, String.format("%02x", startAddress), String.format("%02x", values.size()), value).toUpperCase();
                }else {
                    Integer dataLen = cmdConfig.getInteger("dataLen");
                    content = StringUtils.join(deviceHex, operation, String.format("%02x", startAddress),String.format("%02x", dataLen)).toUpperCase();
                }
                String crc = Utils.checkNumFisrt(content);
                String originalCmd = StringUtils.join("AAAA", crc, content, "5555");

                BigDecimal decimal = new BigDecimal(originalCmd.length());
                int spitCount = decimal.divide(new BigDecimal(16), 0, BigDecimal.ROUND_UP).intValue();
                String cmd = "";
                for (int i = 0; i < spitCount; i++) {
                    String substr;
                    String len = "08";
                    if (i == spitCount - 1) {
                        String substring = originalCmd.substring(i * 16);
                        substr = StringUtils.rightPad(substring, 16, "0");
                        len = String.format("%02x", substring.length() / 2);
                    } else {
                        substr = originalCmd.substring(i * 16, i + 16);
                    }
                    cmd = StringUtils.join(cmd, len, "00000001", substr);
                }

                SendCmd sendCmd = new SendCmd(5, originalCmd.substring(6, 14), 0, source, messageId, deviceHex, port, cmd.toUpperCase(), isSave,true);
                vertx.eventBus().publish(Constant.ONLY_CMD + port, JsonObject.mapFrom(sendCmd));
            });

        }else if (StringUtils.equals(dtuType, Constant.DTUTYPE_13)) {
            String source = cmdConfig.getString("source");
            String messageId = cmdConfig.getString("messageId");
            String operation = cmdConfig.getString("operation");
            String deviceHex = cmdConfig.getString("deviceHex");
            Integer deviceAddr = cmdConfig.getInteger("deviceAddr");
            Boolean isInstantCmd = cmdConfig.getBoolean("isInstantCmd");
            if (isInstantCmd==null){
                isInstantCmd=true;
            }
            Integer defaultPort;
            if (deviceAddr==null){
                deviceAddr=1;
            }
            if(port==null){
                defaultPort=62008;
            }else {
                defaultPort=port;
            }
            String finalDeviceAddr =String.format("%02x",deviceAddr);

            Calendar cal = Calendar.getInstance();
            TimeZone tz = TimeZone.getTimeZone("GMT");
            cal.setTimeZone(tz);

            Integer deviceAddrInteger = deviceAddr;
            Boolean finalIsInstantCmd = isInstantCmd;
            redis.hgetall(BasetVerticle.getRedisKeyByDeviceId(deviceHex), deviceInfoResult -> {
                if (deviceInfoResult.succeeded()) {
                    JsonObject deviceInfo = deviceInfoResult.result();
                    Integer currentRatio = Integer.parseInt(deviceInfo.getString("currentRatio")==null?deviceInfo.getString("currentRatio"):"1");
                    if (currentRatio<1){
                        currentRatio=1;
                    }

                    String pr = "F1";
                    String ver;
                    String ver2;
                    String cmdLen;

                    Object deviceCmdNo= redisTemplate.opsForHash().get(BasetVerticle.getRedisKeyByDeviceId(deviceHex), "cmdNo");
                    int cmdNoInt=201;
                    if (deviceCmdNo!=null&&Integer.parseInt(deviceCmdNo.toString())<60000){
                        cmdNoInt=Integer.parseInt(deviceCmdNo.toString());
                        cmdNoInt++;
                    }
                    redisTemplate.opsForHash().put(BasetVerticle.getRedisKeyByDeviceId(deviceHex), "cmdNo", cmdNoInt+"");
                    String cmdNo = String.format("%04x", cmdNoInt);
                    String time = Long.toHexString(cal.getTimeInMillis() / 1000);
                    String uid = "FFFFFF80";
                    String data = "";
                    ver = "FF";
                    ver2 = "00";
                    if (StringUtils.equals("B5", operation) || StringUtils.equals("B1", operation) || StringUtils.equals("AD", operation)) {
                        ver = "FF";
                    } else if (StringUtils.equals("B0", operation)) {
                        ver = "55";
                        data = "784CD38E242B";
                    } else if (StringUtils.equals("D3", operation)) {
                        String cmdId = cmdConfig.getString("cmdId");
                        ver = cmdId;
                        switch (ver) {
                            case "A1":
                            case "A2":
                                data = StringUtils.join("0000000000000000", finalDeviceAddr);
                                break;
                            case "C3":
                                data = StringUtils.join("00", finalDeviceAddr);
                                break;
                            case "C6":
                            case "C7":
                            case "C8":
                            case "C9":
                            case "CA":
                                Double upperLimit = cmdConfig.getDouble("upperLimit");
                                Double lowerLimit = cmdConfig.getDouble("lowerLimit");
                                BigDecimal mu = new BigDecimal(1);
                                if (StringUtils.equals("C8", ver)) {
                                    mu = new BigDecimal(100).divide(new BigDecimal(currentRatio));
                                } else if (StringUtils.equals("C9", ver) || StringUtils.equals("CA", ver)) {
                                    mu = new BigDecimal(10);
                                } else if (StringUtils.equals("C6", ver)) {
                                    mu = new BigDecimal(1000).divide(new BigDecimal(currentRatio));
                                }
                                data = StringUtils.join(String.format("%04x", new BigDecimal(upperLimit).multiply(mu).intValue()), String.format("%04x", new BigDecimal(lowerLimit).multiply(mu).intValue()), finalDeviceAddr);
                                break;
                            case "D1":
                            case "D6":
                                data = String.format("%04x", Integer.parseInt(cmdConfig.getString("value")));
                                break;

                            case "DF":
                            case "DE":
                                data = finalDeviceAddr;
                                break;
                            case "DA":
                                String value = cmdConfig.getString("value");
                                String pattern = "((2(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})(\\.((2(5[0-5]|[0-4]\\d))|[0-1]?\\d{1,2})){3}";

                                Pattern r = Pattern.compile(pattern);
                                Matcher m = r.matcher(value);
                                if (m.matches()) {
                                    data = StringUtils.join(String.format("%02x", 0), String.format("%04x", 62008),StringUtils.rightPad( getIpStr(value), 58, "0"));
                                } else {
                                    data = StringUtils.join(String.format("%02x", 1), String.format("%04x", 62008),StringUtils.rightPad( Utils.bytes2String(value.getBytes()), 58, "0"));
                                }
                                break;
                            case "DC":
                            case "DD":
                                value = cmdConfig.getString("value");
                                data = StringUtils.join(String.format("%08x", Integer.parseUnsignedInt(value, 2)), "01");
                                break;
                            case "D7":
                                value = cmdConfig.getString("value");
                                data = StringUtils.join(getIpStr(value), String.format("%04x", 62008));
                                break;
                            case "E1":
                            case "E2":
                                value = cmdConfig.getString("value");
                                Integer v = Integer.parseInt(value);
                                data = StringUtils.join(String.format("%02x", v));
                                break;
                            case "E3":
                                data = StringUtils.join(String.format("%08x", (int)Double.parseDouble(cmdConfig.getString("value")) * 1000));
                                break;
                        }
                    }
                    cmdLen = String.format("%04x", data.length() / 2);

                    String preCmd = StringUtils.join(pr, operation, ver, ver2, cmdLen, cmdNo, time, uid, data);
                    String crc = CRC16.calcCrc32(Utils.hexStringToByteArray(preCmd));
                    String cmd = StringUtils.join(preCmd, crc).toUpperCase();
                    SendCmd sendCmd = new SendCmd(2, true, cmdNo.toUpperCase(), 0, source, messageId, defaultPort, cmd.toUpperCase(), deviceHex, deviceAddrInteger);
                    sendCmd.setInstantMessage(finalIsInstantCmd);
                    vertx.eventBus().publish(Constant.ONLY_CMD + defaultPort, JsonObject.mapFrom(sendCmd));
                }

            });


        }
    }

    protected String getIpStr(String ip) {
        String[] split = ip.split("\\.");
        String ipstr="";
        for (int i = 0; i <split.length ; i++) {
            ipstr= StringUtils.join(ipstr, String.format("%02x",Integer.parseInt(split[i])));
        }
        return ipstr;
    }

    public SendCmd lnSendCmd(Integer port, String source,int cmdIdLn, String operation, Integer function, List<String> deviceList,String messageId,Boolean isSave) {

        String splicData = "";
//            List<String> deviceList=Arrays.asList("0", "3", "64");
        String Base_Id;
        String Base_StateType_len;
        int frame_Type =0 ;
        int start_Addr=0;
        int end_Addr=0;
        String CC_Ctrl;
        String CC_Ctrl_Value1="00000000";
        String CC_Ctrl_Value2="00000000";
        String CC_Ctrl_Value3="00000000";
        String CC_McuId="39FF6D065058373730410643";
        String CC_u16s="000000000000";
        String CC_u32s="00000000000000000000000000000000000000000000000000000000000000000000000000000000";

        String cmd_Id = String.format("%04x", cmdIdLn).toUpperCase();

        if(StringUtils.equals(Constant.LNCMDTYPE_CONTRL, operation)) {
            frame_Type = 6;
            start_Addr = 61;
            end_Addr = 68;

            cmd_Id = StrUtils.getSmall(cmd_Id);
            Base_Id = getDataHead(deviceList);

            Base_StateType_len = String.format("%02x", 0);
            String Base_StateType = "";
            CC_Ctrl = StrUtils.getSmall(String.format("%08x", function));
            splicData = Joiner.on("").join(Base_Id, Base_StateType_len, Base_StateType, CC_Ctrl, CC_Ctrl_Value1, CC_Ctrl_Value2, CC_Ctrl_Value3, CC_McuId, CC_u16s, CC_u32s);
        }else if(StringUtils.equals(Constant.LNCMDTYPE_GETALL, operation)) {
            frame_Type = 8;
            start_Addr = 3;
            end_Addr = 13;

            cmd_Id = "6C00";
            Base_Id = getDataHead(deviceList);
            Base_StateType_len = String.format("%02x", 1);
            String Base_StateType = StrUtils.getSmall(String.format("%04x", 1));
            splicData = Joiner.on("").join(Base_Id, Base_StateType_len, Base_StateType);
        }



//            switch (function) {
//
//                case 8:
//                    frame_Type=8;
//                    start_Addr=3;
//                    end_Addr=10;
//                    deviceList=Arrays.asList("0", "3", "64");
//
//                    cmd_Id = "6C00";
//                    Base_Id = getDataHead(deviceList);
//                    Base_StateType_len = String.format("%02x", 1);
//                    String Base_StateType = StrUtils.getSmall(String.format("%04x", 1));
//                    splicData = Joiner.on("").join(Base_Id, Base_StateType_len, Base_StateType);
//                    break;
//                case 14://立刻返回Base_Id中所有设备的 心跳数据包 CB_CurrentInfo
//                    frame_Type=6;
//                    start_Addr=61;
//                    end_Addr=68;
//                    deviceList=Arrays.asList("0");
//
//                    cmd_Id = StrUtils.getSmall("0072");
//                    Base_Id = getDataHead(deviceList);
//                    Base_StateType_len = String.format("%02x", 0);
//                    Base_StateType="";
//                    CC_Ctrl=StrUtils.getSmall("00000069") ;
//
//                    splicData = Joiner.on("").join(Base_Id, Base_StateType_len, Base_StateType,CC_Ctrl,CC_Ctrl_Value1,CC_Ctrl_Value2,CC_Ctrl_Value3,CC_McuId,CC_u16s,CC_u32s);
//                    break;
//                case 15://立刻返回Base_Id中所有设备的 设置基本配置 CB_BaseConfig
//                    frame_Type=6;
//                    start_Addr=61;
//                    end_Addr=68;
//                    deviceList=Arrays.asList("0");
//
//                    cmd_Id = StrUtils.getSmall("0073");
//                    Base_Id = getDataHead(deviceList);
//
//                    Base_StateType_len = String.format("%02x", 0);
//                    Base_StateType="";
//                    CC_Ctrl=StrUtils.getSmall(String.format("%08x", 106)) ;
//                    splicData = Joiner.on("").join(Base_Id, Base_StateType_len, Base_StateType,CC_Ctrl,CC_Ctrl_Value1,CC_Ctrl_Value2,CC_Ctrl_Value3,CC_McuId,CC_u16s,CC_u32s);
//                    break;
//                case 16://立刻返回主设备中的所有设备状态信息 CB_Ctrl
//                    frame_Type=6;
//                    start_Addr=61;
//                    end_Addr=68;
//                    deviceList=Arrays.asList("0");
//
//                    cmd_Id = StrUtils.getSmall("0074");
//                    Base_Id = getDataHead(deviceList);
//
//                    Base_StateType_len = String.format("%02x", 0);
//                    Base_StateType="";
//                    CC_Ctrl=StrUtils.getSmall("0000006B") ;//107
//                    splicData = Joiner.on("").join(Base_Id, Base_StateType_len, Base_StateType,CC_Ctrl,CC_Ctrl_Value1,CC_Ctrl_Value2,CC_Ctrl_Value3,CC_McuId,CC_u16s,CC_u32s);
//                    break;
//                case 19://立刻返回Base_Id中所有设备的 断路器设备基本信息 CB_BaseInfo
//                    frame_Type=6;
//                    start_Addr=61;
//                    end_Addr=68;
//                    deviceList=Arrays.asList("0");
//
//                    cmd_Id = StrUtils.getSmall("0077");
//                    Base_Id = getDataHead(deviceList);
//
//                    Base_StateType_len = String.format("%02x", 0);
//                    Base_StateType="";
//                    CC_Ctrl=StrUtils.getSmall("000000C8") ;//107
//                    splicData = Joiner.on("").join(Base_Id, Base_StateType_len, Base_StateType,CC_Ctrl,CC_Ctrl_Value1,CC_Ctrl_Value2,CC_Ctrl_Value3,CC_McuId,CC_u16s,CC_u32s);
//                    break;
//                case 23:
////                0101000700000000000000000000000000000039ff6d06505837373041064300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f0
//
//                    frame_Type=6;
//                    start_Addr=61;
//                    end_Addr=68;
//                    deviceList=Arrays.asList("1");
//                    cmd_Id = StrUtils.getSmall("007B");
//                    Base_Id = getDataHead(deviceList);
//                    Base_StateType_len = String.format("%02x", 0);
//                    Base_StateType="";
//                    CC_Ctrl=StrUtils.getSmall("00000007") ;
//                    CC_McuId="39FF6D065058373730410643";
//                    splicData = Joiner.on("").join(Base_Id, Base_StateType_len, Base_StateType,CC_Ctrl,CC_Ctrl_Value1,CC_Ctrl_Value2,CC_Ctrl_Value3,CC_McuId,CC_u16s,CC_u32s);
//                    break;
//            }
//        logger.debug("splicData:{}",splicData.toUpperCase());
        String data = StrUtils.decode(Constant.secretkeys.get("6161"), splicData);
        String check = Utils.checkNumFisrt(splicData);
        int bodyLen = splicData.length() / 2 + 21;
        String head = splicHead(bodyLen, frame_Type, start_Addr, end_Addr,cmd_Id);
        String cmd = Joiner.on("").join(head, data,check, "7573").toUpperCase();

//        logger.debug("port:" + port + "-->send cmd:" + cmd);
        SendCmd sendCmd = new SendCmd(1, cmd_Id, 1, source, messageId, "", port, cmd);
        sendCmd.setSave(isSave);
        return sendCmd;
    }


    private static String splicHead(int bodyLen, int frameType, int startAddr, int endAddr,String cmd_Id ) {
        String start = "DCDD00";
        String device_Type = "01";
        String secret_Key = "6161";
        String body_Len = StrUtils.getSmall(String.format("%04x", bodyLen));
        String ppl = "0101";
        String frame_Type = StrUtils.getSmall(String.format("%04x", frameType));
        String start_Addr = StrUtils.getSmall(String.format("%04x", startAddr));
        String end_Addr = StrUtils.getSmall(String.format("%04x", endAddr));
        String join = Joiner.on("").join(start, device_Type, secret_Key, body_Len, ppl, frame_Type, cmd_Id, start_Addr, end_Addr);
        return join;
    }


    private static String getDataHead(List<String> baseId) {
        String Base_Id_len = String.format("%02x", baseId.size());
        return baseId.stream().reduce(Base_Id_len, (s, t) -> {
            String format = String.format("%02x", Integer.parseInt(t));
            String join = Joiner.on("").join(s, format);
            return join;
        });
    }


    public JsonObject getTypeRedis(JsonObject config,String dtuType) {
        if(StringUtils.equals(dtuType, Constant.DTUTYPE_6)){
            getRedis(config);
        }else if(StringUtils.equals(dtuType, Constant.DTUTYPE_7)){
            String[] profiles = context.getEnvironment().getActiveProfiles();
            String address;
            if (Arrays.asList(profiles).contains("pro")){
                address=Constant.PRO_SERVER_ADDR;
            }else {
                address=Constant.TEST_SERVER_ADDR;
            }
            config.put("serverAddress", address);
        }else if (StringUtils.equals(dtuType, Constant.DTUTYPE_8)){
            config.put("cmdList", new ArrayList<>());
            getganwenRedis(config);
        }
        return config;
    }

    public JsonObject getRedis(JsonObject config) {
        JsonObject deviceTypeList = new JsonObject(config.getString("deviceTypeList"));
        JSONArray list = deviceTypeList.stream().map(record -> {
            String deviceNum = record.getKey();
            String deviceType = record.getValue().toString();
            String sendcmd = "";
            Stream<JsonObject> stream = null;
            if (StringUtils.equals(deviceType, Constant.DEVICETYPE_117)) {
                sendcmd = "68" + Utils.checkNumFisrtAll(Utils.addStr("F0", deviceNum, "03", "6003", String.format("%04x", 9)));
            } else if (StringUtils.equals(deviceType, Constant.DEVICETYPE_116) || StringUtils.equals(deviceType, Constant.DEVICETYPE_106)) {
                sendcmd = Utils.checkNumSecondAll(Utils.addStr(deviceNum, "03", "0106", String.format("%04x", 1)));
            }
            return sendcmd;
        }).collect(Collectors.toCollection(JSONArray::new));
        config.put("cmdList", list.toString());
        return config;
    }

    public JsonObject getganwenRedis(JsonObject config) {
        JsonObject deviceTypeList = new JsonObject(config.getString("deviceTypeList"));
        String chananlCount = config.getString("chananlCount");
        List activeCmd = deviceTypeList.stream().flatMap(record -> {
            String deviceType = record.getValue().toString();
            Stream<JsonObject> stream = null;
            if (StringUtils.equals(deviceType, Constant.DEVICETYPE_GANWEN)) {
                List<JsonObject> cmd = new ArrayList<>();
                int partition = Integer.parseInt(chananlCount);
                String[] c = Utils.gancmd(partition);
                for (int i = 0; i < c.length; i++) {
                    cmd.add(new JsonObject().put("isSend", true).put("cmdRate", 60).put("cmd", c[i]));
                }
                stream = cmd.stream();
            }
            return stream;
        }).collect(Collectors.toList());
        config.put("activeCmd", activeCmd);
        return config;
    }

    public static void main(String[] args) {
        String a="{\"01\":\"106\"}";
        JsonObject deviceTypeList = new JsonObject(a);
        System.out.println(deviceTypeList);
    }
}